#include "stdafx.h"

#include "projectheader.h"
#include "../VideoCapture/CamWrapper.h"

void MyMainWindow::videoCaptureSetup() {
	this->frame_timer = new QTimer(this);
	this->second_timer = new QTimer(this);
	this->gtimer = new QTime();
	this->dtimer = new QTime();
	this->p_frame = 0; // For frame rate
	this->gtimer->start();
	this->dtimer->start();
	this->counter=10; // default is 10ms (100 fps)
	this->pause = false;
	this->camHeight = 480.0;
	this->camWidth = 640.0;
	this->camFrame = 100.0;
	this->fps = 500;
	this->cam_num=1;
	ui.action_Device_Ready->setDisabled(false);
	connect(ui.action_Start_Capture,  SIGNAL(triggered()), this, SLOT(startCaptureFromCam()));
	connect(ui.action_Pause_Resume,  SIGNAL(triggered()), this, SLOT(pauseResumeCaptureFromCam()));
	connect(ui.action_Stop_Capture,  SIGNAL(triggered()), this, SLOT(stopCaptureFromCam()));
	connect(frame_timer, SIGNAL(timeout()), this, SLOT(processCapturedFrame())); // When timer gets each interval, it will called
	connect(ui.push_counter_reset, SIGNAL(clicked()), this , SLOT(resetCaptureCounter()));
	connect(second_timer, SIGNAL(timeout()), this, SLOT(displayCurrentFrameProcessRate()));
	connect(ui.action_Frame_Grab, SIGNAL(triggered()), this , SLOT(captureCurrentFrame()));
	connect(ui.actionOnAndOff, SIGNAL(triggered()), this, SLOT(changeOverlayStatus()));
	connect(ui.actionInterleaving, SIGNAL(triggered()), this, SLOT(changeInterleavingVideoStatus()));
	connect(ui.pushButton_listAvailableCam, SIGNAL(clicked()), this, SLOT(ProbeAllCam()));
	connect(ui.pushButton_initCam, SIGNAL(clicked()), this, SLOT(initCam()));
	connect(ui.pushButton_releaseCam, SIGNAL(clicked()), this, SLOT(releaseCam()));
	this->r_frame = 0;
	this->overlayVideo = true;
	this->interleavingVideo = false;
	connect(ui.lcdRange,SIGNAL(valueChanged(int)),this,SLOT(changeCaptureCounterSpeed10xms(int)));
	connect(this,SIGNAL(displayElapsedTimeForCaptureSignal(int)),ui.grab_time,SLOT(display(int)));
	connect(this,SIGNAL(displayElapsedTimeForDisplaySignal(int)),ui.disp_time,SLOT(display(int)));
	ui.actionOnAndOff->setCheckable(true);
	ui.actionOnAndOff->setChecked(true);
	ui.actionInterleaving->setCheckable(true);
	ui.actionInterleaving->setChecked(false);
	this->cameraInput = NULL;
#ifdef NO_AVT_UNIAPI
	ui.checkBox_camInterfaceAvtUniApi->setEnabled(false);
#endif
#ifdef NO_AVT_GIGE
	ui.checkBox_camInterfaceAvtGigE->setEnabled(false);
#endif
#ifdef NO_HIGHGUI_CAM
	ui.checkBox_camInterfaceHighGui->setEnabled(false);
#endif
#ifdef NO_IMAGING_SOURCE
	checkBox_camInterfaceImagingSource->setEnabled(false);
#endif
}


void MyMainWindow::initCam() {
	int index = ui.comboBox_camList->currentIndex();
	if(index<0) return;
	if( this->initCam(ui.comboBox_camList->itemData(index).toInt()) ) {
		ui.action_Device_Ready->setDisabled(true);
		ui.action_Start_Capture->setDisabled(false);
		ui.action_Stop_Capture->setDisabled(false);
		ui.action_Pause_Resume->setDisabled(true);
		ui.comboBox_camList->setItemText(index,QString(ui.comboBox_camList->itemText(index)+" *selected*"));
	}
}

void MyMainWindow::releaseCam() {
	int index = ui.comboBox_camList->currentIndex();
	if(index<0) return;
	if(this->releaseCam(ui.comboBox_camList->itemData(index).toInt())) {
		ui.comboBox_camList->setItemText(index,QString(ui.comboBox_camList->itemText(index).remove(" *selected*")));
	}
}

bool MyMainWindow::initCam(int camId) {
		if(this->cameraInput!=NULL) {
			this->cameraInput->closeCam();
			this->cameraInput->releaseInterface();
		} else {
			this->cameraInput = new CamWrapper();
		}
		CAM_INTERFACE_TYPE iface = camMatrix.at(camId)->camInterface;
		unsigned long uniqueCamID = camMatrix.at(camId)->uniqueId;
		bool result;
		result = this->cameraInput->initInterface(iface);
		result = result ? this->cameraInput->openCam(uniqueCamID) : false;
		return result;
}

bool MyMainWindow::releaseCam(int camId) {
	return this->cameraInput->releaseInterface();
}

void MyMainWindow::ProbeAllCam() {
	if(ui.action_Device_Ready->isEnabled()==false) stopCaptureFromCam();
	for(int i=0; i<camMatrix.size(); i++) {
		delete camMatrix.at(i);
	}
	camMatrix.clear();
	ui.comboBox_camList->clear();
	//camMatrix.resize(128);
        if(ui.checkBox_camInterfaceHighGui->isChecked() && ui.checkBox_camInterfaceHighGui->isEnabled()) this->camProbe((int)CAM_INTERFACE_TYPE_HIGH_GUI);
        if(ui.checkBox_camInterfaceAvtUniApi->isChecked() && ui.checkBox_camInterfaceAvtUniApi->isEnabled()) this->camProbe((int)CAM_INTERFACE_TYPE_AVT_UNIAPI);
        if(ui.checkBox_camInterfaceAvtGigE->isChecked() && ui.checkBox_camInterfaceAvtGigE->isEnabled()) this->camProbe((int)CAM_INTERFACE_TYPE_AVT_GIGE);
        if(camMatrix.size()>0)	for(int i=0; i<camMatrix.size(); i++) {
		cout<<"Cam:"<<i<<" "<<camMatrix.at(i)->camName<<" ("<<camMatrix.at(i)->camIndex<<") \n";
		ui.comboBox_camList->addItem(QString(QString(camMatrix.at(i)->camName.c_str())+"(%1)").arg(i),QVariant(i));
	}
}



void MyMainWindow::camProbe(int iface) {
		if(this->cameraInput!=NULL) {
			this->cameraInput->closeCam();
			this->cameraInput->releaseInterface();
		} else {
			this->cameraInput = new CamWrapper();
		}
		bool result;
		result = this->cameraInput->initInterface((CAM_INTERFACE_TYPE) iface);
		if(!result) {
			std::cerr<<"CamWrapper init failed on interface "<<iface<<".\n";
			return;
		}
		unsigned int cameraCount = 0;
		result = this->cameraInput->probeCam(cameraCount);
		if(!result) {
			std::cerr<<"CamWrapper probe failed on interface "<<iface<<".\n";
			return;
		}
		std::string *camName = new std::string("No Name");
		unsigned long camId;
		for(unsigned int i = 0; i<cameraCount; ++i) {
			result = this->cameraInput->getCamId(i,camId,camName);
			if(!result) {
				std::cerr<<"CamWrapper getCamId failed on interface "<<iface<<".\n";
				return;
			}
			CameraDetails *CamDetail = new CameraDetails( (int) i, (CAM_INTERFACE_TYPE) iface, *camName, camId);
			this->camMatrix.push_back(CamDetail); 
		}
	std::clog<<"Cam interface"<<iface<<" probed\n";
}


void MyMainWindow::cleanUpVideoCapture() {
	if(ui.action_Device_Ready->isEnabled()==false) {
		stopCaptureFromCam();
	}
	if(frame_timer->isActive()) frame_timer->stop();
	if(second_timer->isActive()) second_timer->stop();
}

void MyMainWindow::changeInterleavingVideoStatus() {
	if(this->interleavingVideo) {
		this->interleavingVideo = false;
		//actionOnAndOff->setChecked(false);
	} else {
		this->interleavingVideo = true;
		//actionOnAndOff->setChecked(true);
	}
}

void MyMainWindow::changeOverlayStatus() {
	if(this->overlayVideo) {
		this->overlayVideo = false;
		//actionInterleaving->setChecked(false);
	} else {
		this->overlayVideo = true;
		//actionInterleaving->setChecked(true);
	}
}


void MyMainWindow::resetCaptureCounter() {
	ui.lcdPCounter->display(0);
	ui.lcdRCounter->display(0);
	r_frame=0;
	p_frame=0;
}


void MyMainWindow::captureCurrentFrame()
{
	if(mainImage!=NULL) {
		prepareUndo();
		cvReleaseImage(&mainImage);
		mainImage = NULL;
		std::clog<<"Released Main Image\n";
	}
	this->processCapturedFrame();
}

void MyMainWindow::prepareProcessedImageToDisplay() {
	emit capturedImageSignal(mainImage);
	emit convertCapturedImageToDisplaySignal();
	emit displayElapsedTimeForDisplaySignal(dtimer->elapsed());
	this->setWindowModified(true);
}

void MyMainWindow::changeCaptureCounterSpeed10xms(int x){
	// change capture interval, 0 will try as fast as it gets
	counter = x*10; // BTW x was from dial control on the lower window
}

void MyMainWindow::processCapturedFrame(){
	if(mainImage!=NULL) cvReleaseImage(&mainImage);
	mainImage =cvCloneImage(this->cameraInput->grabDemosaicingImage());

	r_frame++;

	//#endif
	emit displayElapsedTimeForCaptureSignal(gtimer->elapsed());
	gtimer->restart();
	if(ui.checkBox_colourTrack->isChecked()) {
		if(FCFtest->numOfColours>0) {
			this->processLiveColourTracking();
		}
	}
	if(this->overlayVideo) {
		if((!this->interleavingVideo) || (this->interleavingVideo && (r_frame%5 == 0))) { // bit complex
			dtimer->restart();
			emit capturedImageSignal(mainImage);
			emit convertCapturedImageToDisplaySignal();
			emit displayElapsedTimeForDisplaySignal(dtimer->elapsed());
			p_frame++;
		}
	}
	if(ui.checkBox_saveVideoToFile->isChecked()) {
		int value = ui.spinBox_videoSequence->value();
		value++;
		QString filePrefix = ui.lineEdit_saveToPrefix->text();
		filePrefix += QString("%1.bmp").arg(value,8,10,QLatin1Char('0'));
		QByteArray fileArray = filePrefix.toAscii();
		string fileName(fileArray.data());
		cvSaveImage(fileName.c_str(),mainImage);
		ui.spinBox_videoSequence->setValue(value);
	}

}

void MyMainWindow::displayCurrentFrameProcessRate() {
	float p_fps;
	float r_fps;
	r_fps = r_frame * (1000/fps);
	p_fps = p_frame * (1000/fps);
	r_frame = 0;
	p_frame = 0;
	ui.lcdPCounter->display(p_fps);
	ui.lcdRCounter->display(r_fps);
}

void MyMainWindow::initCamDevice()
{

	ui.action_Device_Ready->setDisabled(true);
	ui.action_Start_Capture->setDisabled(false);
	ui.action_Stop_Capture->setDisabled(false);
	ui.action_Pause_Resume->setDisabled(true);
}

void MyMainWindow::startCaptureFromCam()
{

	requestCleanBuffer = true;
	ui.action_Start_Capture->setDisabled(true);
	ui.action_Pause_Resume->setDisabled(false);
	frame_timer->start(counter);
	second_timer->start(fps);
}

void MyMainWindow::pauseResumeCaptureFromCam()
{
	if(pause==false) {
		frame_timer->stop();
		second_timer->stop();

		pause = true;
	}
	else {
		frame_timer->start(counter);
		second_timer->start(fps);

		pause = false;
	}

}

void MyMainWindow::stopCaptureFromCam()
{ // When you try to restart webcam, it got error somehow...
	frame_timer->stop();
	second_timer->stop();

	ui.action_Device_Ready->setDisabled(false);
	ui.action_Start_Capture->setDisabled(true);
	ui.action_Stop_Capture->setDisabled(true);
	ui.action_Pause_Resume->setDisabled(true);

}

